package com.thread;


import java.util.concurrent.*;

/**
 * 线程创建的四种方式
 */
public class CreateThread {

    //第一种，直接new一个Thread类，也叫继承Thread类
    //new一个Thread类
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                //这里编写该线程要执行的任务逻辑
                System.out.println("线程1执行任务1");
            }
        };
        //调用start方法启动线程
        //第一种创建线程方式
        t1.start();
        Mythread t2 = new Mythread();
        t2.start();
        //第二种创建线程方式
        MyRunnable run = new MyRunnable();
        Thread t3 = new Thread(run, "t3");
        t3.start();
        //第三种创建线程的方式
        MyCallable task = new MyCallable();
        //由于Thread构造器要接收的是runnable类型参数，而futuretask实现了runnable接口，所以将callable任务封装到futuretask
        FutureTask<Integer> futureTask = new FutureTask<>(task);
        Thread t4 = new Thread(futureTask, "t4");
        t4.start();
        //还可以用lambda表达式,并且，futuretask可以做到，主线程阻塞，同步等待task的返回结果
        FutureTask<Integer> futureTaskLambda = new FutureTask<>(() -> {
            return 100;
        });
        new Thread(futureTaskLambda, "t5").start();//线程执行
        //主线程同步等待
        Integer result = futureTaskLambda.get();
        //第四种创建线程方式，线程池
        methodExcutor();
    }

    //那么也可以自己写一个类，继承Thread类
    //这里用内部类的方式来体现
    public static class Mythread extends Thread {
        @Override
        public void run() {
            //这里编写线程要执行的任务逻辑
            super.setName("t2");
            System.out.println("线程2执行任务2");
        }
    }

    //第二种，实现Runnable接口，这种情况下适用于，某个类已经继承了其他类，无法再继承Thread类，那么可以将这个类实现Runnable接口，执行线程逻辑
    //将任务放到Thread构造器中执行
    public static class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("线程3执行任务3");
        }
    }

    //第三种，实现CALLABLE接口，配合FutureTask
    //这个方法可以有返回值,并且可以抛出异常，这是和runnable接口最大的不同
    public static class MyCallable implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("线程4执行任务4");
            return 1;
        }
    }

    //第四种，直接使用线程池创建(Excutor框架)
    //优点：可以降低频繁创建和销毁线程造成的性能开销
    public static class TaskExcutor implements Runnable {
        @Override
        public void run() {
            System.out.println("线程5执行任务5");
        }
    }

    public static void methodExcutor() {
        //创建固定大小的线程池
        ExecutorService excutor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 100; i++) {
            excutor.submit(new TaskExcutor());//提交任务到线程池执行
        }
        excutor.shutdown();//记得关闭线程池
    }
}
